import MonsterData from "../game/data/MonsterData";
import { ui } from "../../ui/layaMaxUI";
import Game from "../game/Game";
import HpBarView from "../../module/common/view/HpBarView";
import GameEvent from "../game/GameEvent";
import BulletVO from "../db/vo/BulletVO";
import BulletData from "../game/data/BulletData";
import { GameStateType } from "../game/GameStateType";
import { LayaPoolName } from "../game/LayaPoolName";
import MonsterShader from "../game/shader/HitShader";
import EffectUtil from "../utils/EffectUtil";
import SoundMgr from "../sound/SoundMgr";
import SoundType from "../sound/SoundType";
import { MonsterStateType } from "../game/MonsterStateType";
import BaseMonsterSkill from "../game/skill/monster/BaseMonsterSkill";
import IBaseMonsterSkill from "../game/skill/monster/IBaseMonsterSkill";
import MonsterVO from "../db/vo/MonsterVO";
import { MonsterType } from "../game/MonsterType";



export default class MonsterScript extends Laya.Script3D {


    protected _owner: Laya.Sprite3D;

    protected _monsterData: MonsterData = new MonsterData();

    protected _step = 1;

    protected _isArrive: boolean = false;

    protected _outPut: Laya.Vector3 = new Laya.Vector3();

    protected _movePos: Laya.Vector3[] = [new Laya.Vector3(-3.5, 0, -13.5), new Laya.Vector3(-3.5, 0, 7.5),
    new Laya.Vector3(3.5, 0, 7.5), new Laya.Vector3(3.5, 0, -13.5)];
    // static _movePos: Laya.Vector3[] = [new Laya.Vector3(-4, 0, 10)];

    protected _lerpRate: number = 0;

    protected _distance: Laya.Vector3;

    protected _startPos: Laya.Vector3;

    protected _shadow: ui.moduleView.common.ShadowViewUI;

    private _outPutUIPos: Laya.Vector4 = new Laya.Vector4();

    private _outPutFlyUIPos: Laya.Vector4 = new Laya.Vector4();


    protected _hpBar: HpBarView;

    protected _targetPos: Laya.Vector3 = new Laya.Vector3(0, 0, 0);

    protected _toRotation: Laya.Vector3 = new Laya.Vector3(0, 0, 0);

    protected _monsterShader: MonsterShader;

    protected _shaderTime: number = 0;

    protected _hitShaderTime: number = 150;

    protected _now: number;

    protected _monsterStateType: MonsterStateType = MonsterStateType.IDLE;

    protected _isStuning: boolean = false;

    protected _skills: IBaseMonsterSkill[] = [];

    protected _tween: Laya.Tween;

    protected _isSkipHit: boolean = false;

    protected _isSkipMove: boolean = false;

    protected _isShowHitEffect: boolean = true;

    protected _customMove: Laya.Vector3 = new Laya.Vector3(-3.5, 0, -13.5);

    protected _hitCb = [];

    protected _dieCb = [];

    protected _shadowOffsetX = 0;

    protected _shadowOffsetY = 0;

    public get skills() {
        return this._skills;
    }

    public get hpBar(): HpBarView {
        return this._hpBar;
    }

    public addDieCb(cb) {
        this._dieCb.push(cb);
    }

    public addHitCb(cb) {
        this._hitCb.push(cb);
    }

    public get sp3d() {
        return this._owner;
    }

    public stop() {
        this._tween && this._tween.pause();
    }

    public resume() {
        this._tween && this._tween.resume();
    }

    public get customMove() {
        return this._customMove;
    }

    public get monsterData() {
        return this._monsterData;
    }

    public setSkipHit(isSkip) {
        this._isSkipHit = isSkip;
        if (isSkip === true) {
            this.owner.name = "monsterSkip";
        }
        else {
            this.owner.name = "monster";
        }
    }


    public setShowHitEffect(isShow) {
        this._isShowHitEffect = isShow;
    }

    public setSkipMove(isSkip) {
        this._isSkipMove = isSkip;

    }

    public getMovePos() {
        return this._targetPos;
    }

    public resetScale() {
        this.sp3d.transform.localScaleX = 40;
        this.sp3d.transform.localScaleY = 40;
        this.sp3d.transform.localScaleZ = 40;
    }

    public setScale(value) {
        this._owner.transform.localScaleX = value;
        this._owner.transform.localScaleY = value;
        this._owner.transform.localScaleZ = value;
    }
    public get movePos() {
        return this._movePos;
    }

    public onDestroy() {

        Laya.Tween.clearAll(this._targetPos);
        this._skills.map((skill: IBaseMonsterSkill) => {
            skill.destroy();
        })
        this._hitCb = [];
        super.onDestroy();
    }

    public onUpdate(): void {
        if (this._shaderTime > 0 && Laya.Browser.now() >= this._shaderTime) {
            this._shaderTime = 0;

            this._monsterShader.clearShader();
        }
        if (this._monsterStateType === MonsterStateType.DIED || Game.state === GameStateType.GAME_OVER) {
            return;
        }
        if (this._isSkipMove === false) {
            this._owner.transform.position = this._targetPos;
        }
        else {
            this._owner.transform.position = this._customMove;
        }
        this._owner.transform.localRotationEulerY = this._toRotation.y;
        this.updateUI();

        this._skills.map((skill: IBaseMonsterSkill) => {
            // console.log(skill)

            skill && skill.exec();


        })
    }


    public onTriggerEnter(other: Laya.PhysicsComponent): void {
        // console.log("MonsterScript trigger enter: ", other.owner);
        if(this._monsterStateType===MonsterStateType.DIED){
            return;
        }
        if (this._isSkipHit === false) {
            if (other.owner.name === "projectile") {
                if (this._isShowHitEffect === true) {
                    this._monsterShader.setShader();
                    this._shaderTime = Laya.Browser.now() + this._hitShaderTime;
                }
            }
        }
    }

    public hit(bulletData: BulletData) {
        // console.log("MonsterScript---", this._monsterData.hp, bulletData);
        // console.log(bulletData.attack, this._monsterData.hp)
        let canSkip;
        this._hitCb.map((cb) => {
            if (cb() === true) {
                canSkip = true;
            }
        });
        if (canSkip === true) {
            return;
        }


        let hurt = Math.min(bulletData.attack, this._monsterData.hp);

        this._monsterData.hp -= hurt;
        // console.log("hurt hp=", this._monsterData.hp, hurt);
        if (hurt > 0) {
            this._hpBar && this._hpBar.update(hurt);
        }
        if (this._monsterData.hp <= 0) {
            this._monsterData.hp = 0;
            this.die();
        }
    }

    public die() {
        // console.log("monster dia...")
        if (this._monsterStateType === MonsterStateType.DIED) {
            return;
        }

        let canSkip;
        this._dieCb.map((cb) => {
            if (cb() === true) {
                canSkip = true;
            }
        });
        if (canSkip === true) {
            return;
        }

        this._monsterStateType = MonsterStateType.DIED;

        Game.camera.viewport.project(this._owner.transform.position, Game.projectViewMat, this._outPutFlyUIPos);
        Laya.stage.event(GameEvent.KILL_MONSTER, this._monsterData);
        this._owner.transform.position = new Laya.Vector3(-1000, -1000, -1000);
        this._shadow.x = -10000;
        this._shadow.y = -10000;
        Laya.Pool.recover(LayaPoolName.MONSTER + this._monsterData.id, this._owner);

        if (this._monsterData.monsterType === MonsterType.BOSS) {
            EffectUtil.playDiamondFlyEffect(this._outPutFlyUIPos, Game.flyLayer, () => {

                Game.hero.playerData.diamond += this._monsterData.diamond;

            });
        }
        else {
            EffectUtil.playCoinFlyEffect(this._outPutFlyUIPos, Game.flyLayer, () => {
                Game.hero.playerData.gold += this._monsterData.gold;

            });
        }
    }

    public hideHpBar() {
        this._hpBar.alpha = 0;
    }
    public showHpBar() {
        this._hpBar.alpha = 1;
    }
    public hideShadow() {
        this._shadow.alpha = 0;
    }
    public showShadow() {
        this._shadow.alpha = 1;
    }


    public resetHp() {
        this._hpBar.reset();
        Game.hpLayer.addChild(this._hpBar);
        // console.log(this._hpBar)
        this._monsterData.hp = this._monsterData.maxHp;
    }

    public reset() {

        Laya.Tween.clearAll(this._targetPos);
        this._monsterStateType = MonsterStateType.IDLE;
        this._step = 1;
        this._owner.transform.localRotationEulerY = 0;
        this._toRotation.y = this._owner.transform.localRotationEulerY;
        this._hpBar.reset();
        Game.hpLayer.addChild(this._hpBar);
        this._monsterData.hp = this._monsterData.maxHp;
        this._isArrive = false;

        this._skills.map((skill: IBaseMonsterSkill) => {
            // console.log(skill)
            skill && skill.reset();
        })
    }



    public init(monsterData: MonsterData) {

        // console.log("MonsterScript init.",monsterData)
        Object.assign(this._monsterData, monsterData);
        this._owner = this.owner as Laya.Sprite3D;
        this._toRotation.y = this._owner.transform.localRotationEulerY;
        this._shadow = new ui.moduleView.common.ShadowViewUI();
        this._owner.name = "monster"
        this._monsterData.hp = this._monsterData.maxHp;
        if (this._monsterData.monsterType === MonsterType.BOSS) {
            this._owner.transform.localScale = new Laya.Vector3(100, 100, 100)
            this._shadow.scaleX = 3;
            this._shadow.scaleY = 3;
            this._shadowOffsetY = 10;
            //  console.log(this._shadow)
            // console.log(this._owner.transform)
        }

        Game.footLayer.addChild(this._shadow);

        if (!this._hpBar) {
            this._hpBar = new HpBarView();
        }
        if (this._monsterData.monsterType === MonsterType.BOSS) {
            this._hpBar.init(this._monsterData.maxHp, 2, { x: 1.8, y: 2 });
        }
        else {
            this._hpBar.init(this._monsterData.maxHp, 1, { x: 0.7, y: 0.7 });
        }
        Game.hpLayer.addChild(this._hpBar);

        this._monsterShader = new MonsterShader(this._owner as Laya.MeshSprite3D);

        this._monsterData.skillIds.map((skillId) => {
            let monsterSkill: IBaseMonsterSkill = Laya.ClassUtils.getInstance("MonsterSkill_" + skillId);
            monsterSkill.init(this, skillId);
            this._skills.push(monsterSkill);
        });


    }

    public updateUI() {
        Game.camera.viewport.project(this._owner.transform.position, Game.projectViewMat, this._outPutUIPos);
        this._shadow.pos(this._outPutUIPos.x + this._shadowOffsetX, this._outPutUIPos.y + this._shadowOffsetY + 40);
        this._hpBar.pos(this._outPutUIPos.x, this._outPutUIPos.y - 40);
    }

    public run() {
        this._monsterStateType = MonsterStateType.RUNNING;
        if (this._isArrive === false) {

            if (this._step >= 2) {
                Laya.Tween.to(this._toRotation, { y: this._owner.transform.localRotationEulerY + 90 }, 300);
            }
            this._movePos[this._step - 1].cloneTo(this._targetPos);

            let distance = Laya.Vector3.distance(this._targetPos, this._movePos[this._step]);
            // console.log("distance",distance)
            if (distance < 8) {
                distance = 12;
            }
            // this._monsterData.moveSpeed=400;

            this._tween = Laya.Tween.to(this._targetPos, { x: this._movePos[this._step].x, y: 0, z: this._movePos[this._step].z }, distance * this._monsterData.moveSpeed, null, Laya.Handler.create(this, this.runHandle));

        }
    }

    protected runHandle() {
        // console.log("runHandle",this._monsterStateType)
        if (this._monsterStateType === MonsterStateType.RUNNING) {
            if ((this._step + 1) !== this._movePos.length) {

                this._step++;
                this.run();
            }
            else {
                // console.log("runHandle Arrive")
                if (this._isSkipMove === false) {
                    this.arrive();
                }
            }
        }
    }

    public arrive() {
        this._isArrive = true;
        this._monsterStateType = MonsterStateType.IDLE;
        Laya.stage.event(GameEvent.MISS_MONSTER, this._monsterData.attack);
        Laya.Pool.recover(LayaPoolName.MONSTER + this._monsterData.id, this._owner);
    }

}